#!/usr/bin/env python
# -*- coding:utf-8 -*-
###
# @file          : mlcad2023_bookshelf2pl.py
# @project       : OpenPARF
# @author        : Jing Mai <jingmai@pku.edu.cn>
# @created date  : August 08 2023, 19:45:44, Tuesday
# @brief         :
# -----
# Last Modified: August 19 2023, 21:45:02, Saturday
# Modified By: Jing Mai <jingmai@pku.edu.cn>
# -----
# @history :
# ====================================================================================
# Date         	By     	(version)	Comments
# -------------	-------	---------	--------------------------------------------------
# ====================================================================================
# Copyright (c) 2020 - 2023 All Right Reserved, PKU-IDEA Group
# -----
# This header is generated by VSCode extension psi-header.
# only consider IOs, DSPs and BRAMs
# IO's position are fixed, and are converted from design.pl file.
# DSPs and BRAMs' position are converted from macroplacement.pl file.
###
# %%
import pathlib
import os
import os.path as osp
import argparse


parser = argparse.ArgumentParser()
parser.add_argument('-b', "--bm_dir", type=str, help="the benchmark folder")
parser.add_argument('-p', "--sol_dir", type=str, help="the solution folder (solution.pl)")
args = parser.parse_args()

# %%
design_dir = args.bm_dir
place_dir = args.sol_dir

scl_path = os.path.join(design_dir, "design.scl")
macro_path = os.path.join(place_dir, "macroplacement.pl")
cascaded_shapes_path = os.path.join(design_dir, "design.cascade_shape_instances")
macro_tcl_path = os.path.join(place_dir, "place_macro.tcl")
# %%


def extractCols(scl_path):
    dsp_cols, bram_cols = [], []
    with open(scl_path, "r") as f:
        lines = [line.strip() for line in f.readlines() if not line.startswith("#")]
    for line in lines:
        if line.endswith("DSP") and not line.startswith("SITE"):
            dsp_cols.append(int(line.split()[0]))
        elif line.endswith("BRAM") and not line.startswith("SITE"):
            bram_cols.append(int(line.split()[0]))
    return sorted(list(set(dsp_cols))), sorted(list(set(bram_cols)))

dsp_cols, bram_cols = extractCols(scl_path)

#%%

def macroToVivado(macro_path, cascaded_shapes_path, fp):
    if osp.exists(cascaded_shapes_path):
        with open(cascaded_shapes_path, "r") as f:
            lines = [line.strip() for line in f.readlines() if not line.startswith("#")]
    else:
        lines = []
    flag = 0
    shape_lists = []
    macro_map = dict()
    for line in lines:
        if line.startswith("BEGIN"):
            flag = 1
            shape_lists = []
        elif line.startswith("END"):
            macro_map[shape_lists[0]] = shape_lists
            flag = 0
        elif flag == 1:
            shape_lists.append(line.strip().split()[0])
    with open(macro_path, "r") as f:
        lines = [line for line in f.readlines() if not line.startswith("#")]
    for line in lines:
        name, xx, yy, zz = line.strip().split()
        xx = int(xx)
        yy = int(yy)
        zz = int(zz)
        if "DSP" in name:
            loc_x = dsp_cols.index(xx)
            loc_y = int((yy + 0.5) / 2.5)
            if name in macro_map:
                macro_list = macro_map[name]
                for i, macro in enumerate(macro_list):
                    assert len(macro) > 0
                    fp.write("  %s %s \\\n" % (macro, "DSP48E2_X%dY%d" % (loc_x, loc_y + i)))
            else:
                assert len(name) > 0
                fp.write("  %s %s \\\n" % (name, "DSP48E2_X%dY%d" % (loc_x, loc_y)))
        elif "BRAM" in name:
            loc_x = bram_cols.index(xx)
            loc_y = int(yy // 5)
            if name in macro_map:
                macro_list = macro_map[name]
                for i, macro in enumerate(macro_list):
                    assert len(macro) > 0
                    fp.write("  %s %s \\\n" % (macro, "RAMB36_X%dY%d" % (loc_x, loc_y + i)))
            else:
                assert len(name) > 0
                fp.write("  %s %s \\\n" % (name, "RAMB36_X%dY%d" % (loc_x, loc_y)))


# %%
fp = open(macro_tcl_path, "w")
fp.write("place_cell { \\\n")
macroToVivado(macro_path, cascaded_shapes_path, fp)
fp.write("}\n")
fp.close()
